<?php
/**
 * 调用：
 *  $re = self::owner()->getDataArray();
 *  $re = self::owner()->getDataArray(array('chName','levelId'));
 *  $re = self::owner()->getCategoryTree('0',array('chName','levelId'));
 *  $re = self::owner()->getCategoryTree('5',array('chName','levelId'));
 */
class Category
{
    /**
     * 主键列名
     * @var string
     */
    public $pkColumn     = 'id';

    /**
     * 父类列名
     * @var string
     */
    public $pidColumn    = 'pid';

    public $childKeyName = 'children';

    public $data    = [];

    public $modelClass;

    public function __construct($modelClass = null)
    {
        $this->modelClass = trim($modelClass);
    }

    public static function owner($modelClass = null)
    {
        static $instance = null;

        if ($instance == null) {
            $instance = new self($modelClass);
        }

        return $instance;
    }

    private function checkModel()
    {
        $class_name = $this->modelClass;

        if ( class_exists($class_name) ) {
            return call_user_func(array($class_name,'model'));
        }
        else{
            outputInfo(array(0,$class_name.' 表模型不存在！'));
        }
    }

    public function getData()
    {
        if (!$this->data) {
            $class_name = $this->modelClass;

            if ( class_exists($class_name) ) {
                $this->data = call_user_func(array($class_name,'findAll'));
            } else{
                trigger_error($class_name.' 表模型不存在！', E_USER_ERROR);
            }
        }

        return $this->data;
    }

    /**
     * getDataArray  初始数据转换成的数组
     * @param  array|string  $need | 'all' [需要获取哪些字段值]
     * 1. 'all' 全部字段
     * 2. array('chName','enName') --> 获取数组仅含有 chName enName 字段
     * @return array       [description]
     */
    public function getDataArray(array $need=[])
    {
        $arrayList = array();
        $arr_data  = $this->getData();

        if ($need && is_array($need)) {
            foreach ($arr_data as $item){
                $needArr = array();

                foreach ($need as $val){
                    if (isset($item[$val])) {
                        $needArr[$val] = $item[$val];
                    }else{
                        trigger_error('参数错误！'.$this->modelClass.'不存在字段：'.$val, E_USER_ERROR );
                    }
                }

                $arrayList[] = $needArr;
            }
        } else {
            $arrayList = $arr_data;
        }

        return $arrayList;
    }

    /**
     * [getCategoryArr 指定层级父id(parentId)，获取其下面的子级初始数据数组]
     * @param  string $rootId [ 当等于0时，等同于 调用 getDataArray() ]
     * @param  string $need   @see getDataArray() -- $need
     * @return array
     */
    public function getCategoryArr( $rootId='0', $need='all', $setKey='id')
    {
        $allDataArr  = $this->getDataArray();

        if ($rootId =='0' || $rootId == ''){
            return $allDataArr;
        }

        $arr_result = array();
        $id         = $this->pkColumn;
        $parentId   = $this->pidColumn;

        # 递归获取子级
        $allNeedArr = $this->arrTree($allDataArr,$rootId);

        foreach ($allNeedArr as $value) {
            if (isset($value[$this->childKeyName])) {
                $items = $value[$this->childKeyName];

                foreach ($items as $key => $item) {
                    foreach ($need as $val){
                        if (isset($item[$val])) {
                            $needArr[$val] = $item[$val];
                        }else{
                            trigger_error('参数错误！'.$this->modelClass.'表不存在字段：'.$val, E_USER_ERROR );
                        }
                    }
                    $setKey=='' ? $arr_result[] = $needArr : $arr_result[$item[$setKey]] = $needArr;
                }
            }
        }

        return $arr_result;
    }

    /**
     * getCategory  递归获取树形图
     * @param  string $rootId   [开始层父级id 默认 0，顶级]
     * @param  array|string  $need | 'all' [需要获取哪些字段值，id pid默认含有]
     * 1. 'all' 全部字段
     * 2. array('chName','enName') --> 获取含有 id pid chName enName 字段
     * @param  string  $setKey [需要什么作为 树形数组的 键名，默认：主键id值为键，留空为自增的数字. e.g. id | enName]
     * @return array       [description]
     */
    public function getCategoryTree( $rootId='0',$need='all',$setKey='id' ){
        if( $rootId == '' ) $rootId ='0';

        if(is_array($need)) {
            $need       = array_merge( array($this->pkColumn,$this->pidColumn), $need);
        }

        $arrayList  = $this->getDataArray($need);
        $arr_result = $this->arrTree($arrayList,$rootId,$setKey);

        return $arr_result;
    }

    /**
     * [arrTree 树形数组递归]
     * @param  [type]  $tree    [需要处理的原始数组]
     * @param  integer $rootId  [ 开始层父级id 默认 0，顶级]
     * @param  string  $setKey [需要什么作为 树形数组的 键名，默认：主键id值为键，留空为自增的数字. e.g. id | enName]
     * @return [type]           [description]
     */
    public function arrTree($tree, $rootId = 0,$setKey='id') {
        $return     = array();
        $id         = $this->pkColumn;
        $parentId   = $this->pidColumn;
        $childKey   = $this->childKeyName;

        foreach($tree as $leaf) {
            if($leaf[$parentId] == $rootId) {
                foreach($tree as $subleaf) {
                    if($subleaf[$parentId] == $leaf[$id]) {
                        $leaf[$childKey] = $this->arrTree($tree, $leaf[$id],$setKey);
                        break;
                    }
                }

                $setKey=='' ? $return[] = $leaf : $return[$leaf[$setKey]] = $leaf;
            }
        }

        return $return;
    }


}